home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / ctask.zip / TSKPRT.C < prev    next >
C/C++ Source or Header  |  1988-07-01  |  10KB  |  386 lines

  1. /*
  2.    TSKPRT.C - CTask - Printer interface routines.
  3.  
  4.    Public Domain Software written by
  5.       Thomas Wagner
  6.       Patschkauer Weg 31
  7.       D-1000 Berlin 33
  8.       West Germany
  9. */
  10.  
  11.  
  12. #include "tsk.h"
  13. #include "prt.h"
  14.  
  15. #define STKSZ     256   /* Printer Task stack size */
  16.  
  17. /*
  18.    The following values may need some tuning for optimum performance.
  19. */
  20. /* 
  21.    MAX_WAIT_xx: Maximum number of times through the loop when waiting
  22.                 for the printer to get ready.
  23. */
  24.  
  25. #define MAX_WAIT_INT    30 /* For interrupt output */
  26. #define MAX_WAIT_POLL   30 /* For polling output */
  27.  
  28. /* 
  29.    xx_DELAY: Ticks to wait before trying again when printer was not ready.
  30. */
  31.  
  32. #define INT_DELAY    5L  /* For interrupt output */
  33. #define POLL_DELAY   5L  /* For polling output */
  34.  
  35. #define INT_TIMEOUT  2L  /* Timeout for ACK interrupt wait */
  36.  
  37.  
  38. typedef void (interrupt far * intprocptr)(void);
  39.  
  40. #define inta00    0x20   /* 8259 interrupt controller control-port */
  41. #define inta01    0x21   /* 8259 interrupt controller mask-port */
  42.  
  43. #define rdserv    0x0b   /* read service register control value */
  44. #define eoi       0x20   /* end of interrupt signal for 8259 */
  45.  
  46. #define data      0x00
  47. #define status    0x01
  48. #define control   0x02
  49.  
  50. #define STROBE    0x01
  51. #define IRQENA    0x10
  52.  
  53. #define dflt_control    (INIT | SELECT)
  54.  
  55.  
  56. /*
  57.    To add support for other LPT-Ports, define
  58.       - Port base
  59.       - IRQ-Bit (optional)
  60.       - Interrupt vector (optional)
  61.    here, add the necessary data to the pr_port_descr array, and, if irq
  62.    was specified, define the corresponding interrupt function by 
  63.    duplicating prtint0, replacing the index into the prt_data array.
  64. */
  65.  
  66. #define PORTS  3              /* Number of defined ports */
  67.  
  68. #define lpt1_base    0x3bc    /* LPT1 port base (mono card) */
  69. #define lpt2_base    0x378    /* LPT2 port base (IBM printer adapter) */
  70. #define lpt3_base    0x278    /* LPT3 port base (secondary parallel) */
  71.  
  72. #define lpt1_irq     0x80     /* IRQ-Bit for LPT1 */
  73. #define lpt2_irq     0x80     /* IRQ-Bit for LPT2 */
  74. #define lpt3_irq     0x20     /* IRQ-Bit for LPT3 */
  75.  
  76. #define lpt1_vect    0x0f     /* Interrupt vector for LPT1 */
  77. #define lpt2_vect    0x0f     /* Interrupt vector for LPT2 */
  78. #define lpt3_vect    0x0d     /* Interrupt vector for LPT3 */
  79.  
  80. typedef struct {
  81.                intprocptr  proc;
  82.                int         base;
  83.                byte        irq;
  84.                byte        vector;
  85.                } port_data;
  86.  
  87. local void interrupt far prtint0 (void);
  88. local void interrupt far prtint1 (void);
  89. local void interrupt far prtint2 (void);
  90.  
  91. port_data pr_port_descr [PORTS] = {
  92.                                  { prtint0, lpt1_base, lpt1_irq, lpt1_vect },
  93.                                  { prtint1, lpt2_base, lpt2_irq, lpt2_vect },
  94.                                  { prtint2, lpt3_base, lpt3_irq, lpt3_vect }
  95.                                   };
  96.  
  97. /*-------------------------------------------------------------------------*/
  98.  
  99. typedef struct {
  100.                farptr   savvect;       /* Interrupt vector save location */
  101.                int      port_base;     /* Port base I/O address */
  102.                byte     irqbit;        /* IRQ-Bit for this port */
  103.                byte     civect;        /* Interrupt Vector for this port */
  104.                byte     wait_xmit;     /* Transmit delayed */
  105.                byte     xmit_pending;  /* Transmit in progress */
  106.                byte     polling;       /* Use polling if on */
  107.                     byte        ccontrol;        /* Current control reg */
  108.                pipe     xmit_pipe;     /* Transmit pipe */
  109.                flag     pready;        /* Printer ready flag */
  110.                tcb      pr_task;       /* Printer task */
  111.                byte     pr_stack [STKSZ]; /* Printer task stack */
  112.                } prt_datarec;
  113.  
  114. typedef prt_datarec *prtptr;
  115.  
  116. local prt_datarec prt_data [PORTS];
  117. local int prt_installed [PORTS] = { 0 };
  118.  
  119. extern funcptr prt_remove_func;
  120.  
  121. /*-------------------------------------------------------------------------*/
  122.  
  123.  
  124. local void near prtint (prtptr prt)
  125. {
  126.    /* Turn off int */
  127.    prt->ccontrol &= ~IRQENA;
  128.    tsk_outp (prt->port_base + control, prt->ccontrol);
  129.  
  130.    /* Signal print char complete */
  131.    set_flag (&prt->pready);
  132.    tsk_outp (inta00, eoi);
  133. }
  134.  
  135.  
  136. local void interrupt far prtint0 (void)
  137. {
  138.    prtint (&prt_data [0]);
  139. }
  140.  
  141. local void interrupt far prtint1 (void)
  142. {
  143.    prtint (&prt_data [1]);
  144. }
  145.  
  146. local void interrupt far prtint2 (void)
  147. {
  148.    prtint (&prt_data [2]);
  149. }
  150.  
  151. /*-------------------------------------------------------------------------*/
  152.  
  153.  
  154. local void near pr_toggle_strobe (int port_base, byte ctl)
  155. {
  156.    tsk_outp (port_base + control, ctl | STROBE);
  157.    tsk_nop ();
  158.    tsk_outp (port_base + control, ctl);
  159. }
  160.  
  161. local int near pr_ready (int port_base)
  162. {
  163.    return (tsk_inp (port_base + status) & (BUSY | ACK | PEND | SELIN | ERROR))
  164.           == (BUSY | ACK | SELIN | ERROR);
  165. }
  166.  
  167.  
  168. local void near pr_output_poll (prtptr prt, byte ch)
  169. {
  170.    int wait_count;
  171.    int port_base;
  172.  
  173.    port_base = prt->port_base;
  174.    while (!pr_ready (port_base))
  175.       {
  176.       for (wait_count = 0; wait_count < MAX_WAIT_POLL; wait_count++)
  177.          if (pr_ready (port_base))
  178.             break;
  179.       if (!pr_ready (port_base))
  180.          t_delay (POLL_DELAY);
  181.       }
  182.    tsk_outp (port_base + data, ch);
  183.    pr_toggle_strobe (port_base, prt->ccontrol);
  184. }
  185.  
  186.  
  187. local void near pr_output_int (prtptr prt, byte ch)
  188. {
  189.    int wait_count;
  190.    int port_base;
  191.  
  192.    port_base = prt->port_base;
  193.    while (!pr_ready (port_base))
  194.       {
  195.       for (wait_count = 0; wait_count < MAX_WAIT_INT; wait_count++)
  196.          if (pr_ready (port_base))
  197.             break;
  198.       if (!pr_ready (port_base))
  199.          t_delay (INT_DELAY);
  200.       }
  201.  
  202.    clear_flag (&prt->pready);
  203.  
  204.    tsk_outp (port_base + data, ch);
  205.    pr_toggle_strobe (port_base, prt->ccontrol | IRQENA);
  206.  
  207.    for (wait_count = 0; wait_count < MAX_WAIT_INT; wait_count++)
  208.       if (check_flag (&prt->pready))
  209.          return;
  210.  
  211.    if (wait_flag_set (&prt->pready, INT_TIMEOUT) < 0)
  212.       tsk_outp (prt->port_base + control, prt->ccontrol &= ~IRQENA);
  213. }
  214.  
  215.  
  216. local void far pr_task (prtptr prt)
  217. {
  218.    int ch;
  219.  
  220.    while (1)
  221.       {
  222.       ch = read_pipe (&prt->xmit_pipe, 0L);
  223.       if (prt->polling)
  224.          pr_output_poll (prt, (byte)ch);
  225.       else
  226.          pr_output_int (prt, (byte)ch);
  227.       }
  228. }
  229.  
  230. /*-------------------------------------------------------------------------*/
  231.  
  232. int far prt_install (int port, byte polling, word prior,
  233.                      farptr xmitbuf, word xmitsize)
  234. {
  235.    prtptr prt;
  236.    int pbase;
  237.    intprocptr far *intptr;
  238. #if (TSK_NAMEPAR)
  239.    static char name [] = "PRTn";
  240.  
  241.    name [3] = (char)(port & 0x7f) + '0';
  242. #endif
  243.  
  244.    if (port & 0x80)
  245.       {
  246.       port &= 0x7f;
  247.       if (port > 4)
  248.          return -1; 
  249.       pbase = *((wordptr)(MK_FP (0x40, port * 2 + 8)));
  250.       if (!pbase)
  251.          return -1;
  252.  
  253.       for (port = 0; port < PORTS; port++)
  254.          if (pr_port_descr [port].base == pbase)
  255.             break;
  256.       }
  257.  
  258.    if (port < 0 || port >= PORTS || !xmitsize || prt_installed [port])
  259.       return -1;
  260.  
  261.    prt = &prt_data [port];
  262.  
  263.    if (create_pipe (&prt->xmit_pipe, xmitbuf, xmitsize
  264. #if (TSK_NAMEPAR)
  265.                    , name
  266. #endif
  267.                    ) == NULL)
  268.       return -1;
  269.  
  270.    create_flag (&prt->pready
  271. #if (TSK_NAMEPAR)
  272.                 , name
  273. #endif
  274.                 );
  275.  
  276.    create_task (&prt->pr_task, pr_task, prt->pr_stack, STKSZ, prior, prt
  277. #if (TSK_NAMEPAR)
  278.                 , name
  279. #endif
  280.                 );
  281.  
  282.    pbase = prt->port_base = pr_port_descr [port].base;
  283.    prt->civect = pr_port_descr [port].vector;
  284.    prt->irqbit = pr_port_descr [port].irq;
  285.    prt->ccontrol = dflt_control;
  286.    prt->wait_xmit = prt->xmit_pending = 0;
  287.  
  288.    if (!prt->irqbit)
  289.       polling = 1;
  290.  
  291.    prt->polling = polling;
  292.  
  293.    tsk_outp (pbase + control, dflt_control);
  294.    if (!polling)
  295.       {
  296.       intptr = (intprocptr far *)MK_FP (0, prt->civect * 4);
  297.       tsk_cli ();
  298.       prt->savvect = *intptr;
  299.       *intptr = pr_port_descr [port].proc;
  300.       tsk_sti ();
  301.       tsk_outp (inta01, tsk_inp (inta01) & ~prt->irqbit);
  302.       }
  303.  
  304.    prt_installed [port] = 1;
  305.    prt_remove_func = prt_remove_all;
  306.    start_task (&prt->pr_task);
  307.  
  308.     return port;
  309.    }
  310.  
  311.  
  312. void far prt_remove (int port)
  313.    {
  314.    prtptr prt;
  315.    intprocptr far *intptr;
  316.  
  317.    prt = &prt_data [port];
  318.    tsk_outp (prt->port_base + control, prt->ccontrol & ~IRQENA);
  319.  
  320.    if (!prt->polling)
  321.       {
  322.       tsk_outp (inta01, tsk_inp (inta01) | prt->irqbit);
  323.       intptr = (intprocptr far *)MK_FP (0, prt->civect * 4);
  324.       tsk_cli ();
  325.       *intptr = prt->savvect;
  326.       tsk_sti ();
  327.       }
  328.    kill_task (&prt->pr_task);
  329.    delete_pipe (&prt->xmit_pipe);
  330.    delete_flag (&prt->pready);
  331.  
  332.    prt_installed [port] = 0;
  333.    }
  334.  
  335.  
  336. void far prt_remove_all (void)
  337. {
  338.    int i;
  339.  
  340.    for (i = 0; i < PORTS; i++)
  341.       if (prt_installed [i])
  342.          prt_remove (i);
  343. }
  344.  
  345.  
  346. /*-------------------------------------------------------------------------*/
  347.  
  348.  
  349. void far prt_change_control (int port, byte ctl)
  350. {
  351.    prtptr prt;
  352.    CRITICAL;
  353.  
  354.    prt = &prt_data [port];
  355.    C_ENTER;
  356.    prt->ccontrol = (prt->ccontrol & ~(AUTOFEED | INIT | SELECT))
  357.                    | (ctl & (AUTOFEED | INIT | SELECT));
  358.    C_LEAVE;
  359.    tsk_outp (prt->port_base + control, prt->ccontrol);
  360. }
  361.  
  362.  
  363. int far prt_write (int port, byte ch, dword timeout)
  364. {
  365.    return write_pipe (&prt_data [port].xmit_pipe, ch, timeout);
  366. }
  367.  
  368.  
  369. int far prt_status (int port)
  370. {
  371.    return tsk_inp (prt_data [port].port_base + status);
  372. }
  373.  
  374.  
  375. int far prt_complete (int port)
  376. {
  377.    return (check_pipe (&prt_data [port].xmit_pipe) == -1);
  378. }
  379.  
  380.  
  381. int far prt_wait_complete (int port, dword timeout)
  382. {
  383.    return wait_pipe_empty (&prt_data [port].xmit_pipe, timeout);
  384. }
  385.  
  386.